 package micropascalcomp.FSA;

import java.io.*;
import micropascalcomp.MP_Token;
import micropascalcomp.Token;

/**
 * Method that acts as a FSA to find digit tokens
 * @author Jason Welch, Codi Gann, Jamal Martin
 */
public class DigitFSA implements FSABehavior {

    public MP_Token getToken(FileReader file, LineNumberReader inFile, int colNum) {
        MP_Token var = null; //token class to be returned
        int readChar;
        int state = 1;
        int column = 3;
        String lexeme = ""; //var to hold the lexeme string

        do {
            try//start of my control loop
            {
                //Start state critera
                readChar = inFile.read();       //grab the first char for the tolken
                lexeme = "" + (char) readChar;
                inFile.mark(column);            //place pointer

                //State 1 initial integers
                while (state == 1) {
                    readChar = inFile.read();   //grab the first char for the state
                    column++;

                    //integers 0....9
                    if (readChar >= 48 && readChar <= 57) {
                        lexeme = lexeme + (char) readChar;
                        inFile.mark(column);                //place pointer
                    } else if (readChar == 46) {
                        //case for period and then set state to 2 
                        state = 2;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                    } else if (readChar == 69 || readChar == 101) {
                        //case for exponetials and then set state to 4
                        state = 4;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                    } else {
                        //this is an escape statment for \n or anything other than a integer or a period
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_INTEGER_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

                //State 2 the period of a decimal number
                while (state == 2) {
                    readChar = inFile.read();               //grab the first char for the token
                    column++;

                    //state two 0...9 
                    if (readChar >= 48 && readChar <= 57) {
                        state = 3;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                        inFile.mark(column);                //place pointer
                    } else {
                        //this is an escape statment for \n or anything other than a integer
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        lexeme = lexeme.substring(0, lexeme.length() - 1);
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_INTEGER_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

                //State 3 fixed point number
                while (state == 3) {
                    readChar = inFile.read();               //grab the first char for the token
                    column++;

                    //integers 0....9
                    if (readChar >= 48 && readChar <= 57) {
                        lexeme = lexeme + (char) readChar;
                        inFile.mark(column);                //place pointer
                    } else if (readChar == 69 || readChar == 101) {
                        //if statment for E(69) or e(101)
                        state = 4;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                        //inFile.mark(column);                //place pointer
                    } else {
                        //this is an escape statment for anything other than a integer, E or e character
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_FIXED_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

                //State 4 The E || e state
                while (state == 4) {
                    readChar = inFile.read();       //grab the first char for the token
                    column++;

                    //integers 0...9 
                    if (readChar >= 48 && readChar <= 57) {
                        state = 6;
                        lexeme = lexeme + (char) readChar;
                        inFile.mark(column);                //place pointer
                    } else if (readChar == 43 || readChar == 45) {
                        //if statment for +(43) or -(45)
                        state = 5;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                        //inFile.mark(column);                //place pointer
                    } else {
                        //this is an escape statment for anything other than a integer, + or - charecter
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        lexeme = lexeme.substring(0, lexeme.length() - 1);
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_FIXED_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

                //State 5 The + || - state following an E || e
                while (state == 5) {
                    readChar = inFile.read();       //grab the first char for the tolken
                    column++;

                    //integers 0...9 
                    if (readChar >= 48 && readChar <= 57) {
                        state = 6;
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                        inFile.mark(column);                //place pointer
                    } else {
                        //this is an escape statment for anything other than an integer
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        lexeme = lexeme.substring(0, lexeme.length() - 2);
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_FIXED_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

                //State 6 Floating point number state
                while (state == 6) {
                    readChar = inFile.read();       //grab the first char for the tolken
                    column++;
                    
                    //integers 0....9
                    if (readChar >= 48 && readChar <= 57) {
                        lexeme = lexeme + (char) readChar;  //add it to the lexeme string
                        inFile.mark(column);                //place pointer
                    } else {
                        //this is an escape statment for anything other than a integer
                        if (readChar == 10 || readChar == 13) {
                            inFile.setLineNumber(inFile.getLineNumber() - 1);
                        }
                        inFile.reset();                     //place pointer back before illegal char
                        return var = new MP_Token(Token.MP_FLOAT_LIT, lexeme, inFile.getLineNumber(), colNum);
                    }
                }

            } catch (IOException e) {
                System.out.println(e);
            }
        } while (true);

    }
}
